package personajes;

import fabricas.FabricaTiempo;
import interfaces.ILaberinto;
import interfaces.IObjetoComible;
import interfaces.IPacman;
import laberinto.Casilla;
import utilidades.Constantes;
import utilidades.ContadorDeCiclos;
import utilidades.Vector;

public class Pacman implements IPacman {
	protected Casilla casillaActual, casillaInicial;
	protected ContadorDeCiclos contadorParaMoverse;
	protected Vector direccionActual,ultimaDireccion;
	protected int puntaje = 0;
	protected int vidas;
	private boolean modoAutomatico;
	private ILaberinto laberinto;
	
	public Pacman(Casilla casillaInicial){
		this.casillaInicial = casillaInicial;
		this.casillaActual = casillaInicial;
		this.vidas = Constantes.VIDAS_PACMAN;
		this.contadorParaMoverse = FabricaTiempo.crearContadorDeCiclos(Constantes.CICLOS_PARA_MOVERSE);
		this.direccionActual = Constantes.NULO;
		this.ultimaDireccion = Constantes.NULO;
		this.modoAutomatico = false;
	}

	public Pacman(ILaberinto laberinto){
		this.laberinto = laberinto;
		this.casillaInicial = laberinto.obtenerCasillaInicialPacman();
		this.casillaActual = laberinto.obtenerCasillaInicialPacman();
		this.vidas = Constantes.VIDAS_PACMAN;
		this.contadorParaMoverse = FabricaTiempo.crearContadorDeCiclos(Constantes.CICLOS_PARA_MOVERSE);
		this.direccionActual = Constantes.NULO;
		this.ultimaDireccion = Constantes.NULO;
		this.modoAutomatico = false;
	}

	
	public void cambiarLaberintoOriginalPor(ILaberinto nuevoLaberinto){
		this.laberinto = nuevoLaberinto;
		
		this.casillaInicial = laberinto.obtenerCasillaInicialPacman();
		this.casillaActual = laberinto.obtenerCasillaInicialPacman();
		
		this.contadorParaMoverse = FabricaTiempo.crearContadorDeCiclos(Constantes.CICLOS_PARA_MOVERSE);
		this.direccionActual = Constantes.NULO;
		this.ultimaDireccion = Constantes.NULO;
	}
	
	//@Override
	public void cambiarCasillaInicial(Casilla casillaInicial){
		this.casillaInicial = casillaInicial;
		this.casillaActual = this.casillaInicial;
	}
	
	public void movimientoAIzquierda(){
		direccionActual = Constantes.IZQUIERDA;
		ultimaDireccion = direccionActual;
	}
	
	public void movimientoADerecha(){
		direccionActual = Constantes.DERECHA;
		ultimaDireccion = direccionActual;
	}

	public void movimientoArriba(){
		direccionActual = Constantes.ARRIBA;
		ultimaDireccion = direccionActual;
	}
	
	public void movimientoAbajo(){
		direccionActual = Constantes.ABAJO;
		ultimaDireccion = direccionActual;
	}
	
	public Casilla obtenerCasilla(){
		return casillaActual;
	}		

	private void resetearCasilla(){
		casillaActual = casillaInicial;
		comerObjetosComibles();
	}
	
	@Override
	public void matar() {
		vidas--;
		vista.Audio.reproducirSonido(Constantes.CLIP_MUERTE_PACMAN); 		
		if(vidas >= 1){
			resetearCasilla();
			direccionActual = new Vector();
		}else{
			System.exit(0);
		}
	}

	@Override
	public void vivir(int tickActual) {
		
		mover(tickActual);
	}	
	
	private void mover(int tickActual){
		comerObjetosComibles();
		if(seMueve()){
			comerObjetosComibles();
			if(!direccionActual.esIgualA(Constantes.NULO)){
				moverse(direccionActual);
			}
			comerObjetosComibles();
		}
	}
	
	private boolean seMueve(){
		float avance = Constantes.VELOCIDAD_PACMAN;
		
		if(contadorParaMoverse.ocurreEnEsteCiclo(avance) && !estaMuerto())
			return true;
		return false;
	}
	
	public void moverse(Vector direccion){
		Casilla destino = casillaActual.obtenerDestino(direccion);
	
		if(destino.esOcupable()){
			casillaActual = destino;
		}
		
		if(!modoAutomatico)
			direccionActual = Constantes.NULO;	
	}

	private void comerObjetosComibles() {
		casillaActual.interaccionDeComiblesCon(this);
	}

	@Override
	public void sacarContenidoDeCasilla(IObjetoComible oComible){
		laberinto.sacarContenidoDeCasilla(oComible,casillaActual.obtenerIdCasilla());
	}
	
	@Override
	public boolean estaMuerto() {
		return vidas <= 0;
	}
	
	@Override
	public Vector obtenerPosicion() {
		return casillaActual.obtenerPosicion();
	}
	
	public String obtenerDireccionEnTexto(){	
		return (direccionActual!=null) ? direccionActual.convertirATexto() : " ";
	}
		
	public boolean esUnPacmanNulo(){
		return false;
	}

	@Override
	public void CambiarModoDeMovimiento(){
		modoAutomatico = !modoAutomatico;
	}

	@Override
	public Vector obtenerDireccion() {
		return direccionActual;
	}

	@Override
	public void incrementarPuntaje(int puntos) {
		puntaje += puntos;
		
	}

	@Override
	public int obtenerPuntaje() {
		return puntaje;
	}

	@Override
	public Vector obtenerUltimaDireccion() {
		return ultimaDireccion;
	}

	@Override
	public int obtenerVidas() {
		return vidas;
	}
}
